#include <config.h>
#include <input_manager.h>
#include <disp_manager.h>
#include <stdlib.h>
 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 #include <unistd.h>

#include <linux/input.h>
/*
struct input_event {    // <linux/input.h> 中定义
	struct timeval time;   // 事件发生的时间
	__u16 type;            // 事件类型如 EV_KEY EV_REL
	__u16 code;            // 事件代码如 REL_X REL_Y BTN_LEFT
	__s32 value;           // 事件的值
};*/

#define MAX(a,b) (((a) > (b))? (a) : (b))
#define MIN(a,b) (((a) < (b))? (a) : (b))

static int giFd;
static int giPosX;	// 默认居中显示鼠标
static int giPosY;
static int giPosXres;
static int giPosYres;
static int giPressure;


/**********************************************************************
 * 函数名称： MouseDevInit
 * 功能描述： 鼠标输入模块的设备初始化函数
 * 
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
static int MouseDevInit(void)
{
	giFd = open(MOUSE_EVENT, O_RDONLY);
	if(giFd < 0){
		DBG_PRINTF("can not open "MOUSE_EVENT);
		return -1;
	}
	int iBpp;
	if (GetDispResolution(&giPosXres, &giPosYres, &iBpp))
	{
		return -1;
	}
	giPosX = giPosXres / 2; // 默认居中显示鼠标
	giPosY = giPosYres / 2 - 100;
	return 0;
}

/**********************************************************************
 * 函数名称： StdinDevExit
 * 功能描述： 鼠标输入模块的设备退出函数
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
static int MouseDevExit(void)
{
	close(giFd);
	return 0;
}


/**********************************************************************
 * 函数名称： MouseGetInputEvent
 * 功能描述： 鼠标输入模块的读取数据函数,它在鼠标输入模块的子线程中被调用
 * 输入参数： 无
 * 输出参数： ptInputEvent - 内含得到的输入数据
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
static int MouseGetInputEvent(PT_InputEvent ptInputEvent)
{
	struct input_event tEvent;
	int iLen;

	while (1)
	{
		iLen = read(giFd, &tEvent, sizeof(tEvent)); /* 如果无数据则休眠 */
		if (iLen != sizeof(tEvent))
			DBG_PRINTF("read input_event form mouse failed.\n");
		if (tEvent.type == EV_KEY)
		{
			if (tEvent.code == BTN_LEFT)
				giPressure = tEvent.value;
			else
				continue;
		}
		else if (tEvent.type == EV_REL)
		{
			if (tEvent.code == REL_X ){
				giPosX += tEvent.value;
				giPosX = MAX(giPosX, 0);
				giPosX = MIN(giPosX, giPosXres);
				giPressure = MOUSE_MOVE;
			}
			else if ( tEvent.code == REL_Y){
				giPosY += tEvent.value;
				giPosY = MAX(giPosY, 0);
				giPosY = MIN(giPosY, giPosYres);
				giPressure = MOUSE_MOVE;
			}
			else 
				continue;
		}
		else if (tEvent.type == EV_ABS)
		{
			if (tEvent.code == ABS_X )
				giPosX = tEvent.value;
			else if (tEvent.code == ABS_Y)
				giPosY = tEvent.value;
			else 
				continue;
		}
		else 
			continue;
		
		ptInputEvent->tTime     = tEvent.time;
		ptInputEvent->iType     = INPUT_TYPE_MOUSE;
		ptInputEvent->iX        = giPosX;
		ptInputEvent->iY        = giPosY;
		ptInputEvent->iPressure = giPressure;
		return 0;
	}

	return 0;
}


static T_InputOpr g_tMouseOpr = {
	.name          = "Mouse",
	.DeviceInit    = MouseDevInit,
	.DeviceExit    = MouseDevExit,
	.GetInputEvent = MouseGetInputEvent,
};

/**********************************************************************
 * 函数名称： MouseInit
 * 功能描述： 注册"鼠标输入模块"
 * 输入参数： 无
 * 输出参数： 无
 * 返 回 值： 0 - 成功, 其他值 - 失败
 * 修改日期        版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2013/02/08	     V1.0	  韦东山	      创建
 ***********************************************************************/
int MouseInit(void)
{
	return RegisterInputOpr(&g_tMouseOpr);
}

